import { AntDesignTheme, IAssemblyDocTreeNode, Types } from '@amcax/base';
import { DraggableModal } from '@app-base/common/components/draggable-modal/DraggableModal';
import { ProductTreeNode } from '@app-cad-env/product/widgets/LeftPanel/types';
import { MultipleSelectList } from '@app-cad/common/components/MultipleSelectList';
import { PRODUCT_EVENT } from '@app-cad/common/Constants';
import { DocumentContext } from '@app-cad/common/providers/documentProvider';
import { MessageTip } from '@app-cad/common/utils/MessageTip';
import { ctx2, userEvents } from '@app-cad/module';
import { buildAssemblyTree } from '@app-cad/pages/product-support/assembly-funcs';
import {
  getPartRefKey,
  removeRefDocObjects,
} from '@app-cad/pages/product-support/part-funcs';
import { Button, Col, ConfigProvider, Row, Space, Tooltip } from 'antd';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { VscArrowDown, VscArrowUp, VscGitCompare } from 'react-icons/vsc';

interface ResortDocModalProps {
  open: boolean;
  onClose: () => void;
  treeNode: ProductTreeNode | undefined;
}

function findNodeByKey(
  tree: ProductTreeNode | undefined,
  key: string,
): ProductTreeNode | undefined {
  if (!tree) {
    return undefined;
  }
  if (tree.key === key) {
    return tree;
  }
  if (tree.children) {
    for (const child of tree.children) {
      const found = findNodeByKey(child, key);
      if (found) {
        return found;
      }
    }
  }
  return undefined;
}

const ResortDocModal: React.FC<ResortDocModalProps> = ({
  open,
  onClose,
  treeNode,
}) => {
  const { docTree } = useContext(DocumentContext);
  const [selectedKeys, setSelectedKeys] = useState<string[]>([]);

  // retrieve the node by key in case the tree structure is rebuilt by calling buildAssemblyTree
  const {
    key,
    type,
    children = [],
    assembly,
  } = findNodeByKey(docTree, treeNode?.key || '') || {};

  let itemsToReorder: ProductTreeNode[];
  if (key === docTree.key || type === 'product') {
    itemsToReorder = children.filter(({ type }) =>
      ['product', 'part'].includes(type),
    );
  } else {
    itemsToReorder = children.filter(({ type }) => {
      return type === Types.GeomBox || type === Types.GeomSet;
    });
  }

  const canMove = selectedKeys.length === 1;
  const canSwap = selectedKeys.length === 2;

  let isFirst = false;
  let isLast = false;
  if (canMove) {
    const idx = itemsToReorder.findIndex(
      (item) => item.key === selectedKeys[0],
    );
    isFirst = idx === 0;
    isLast = idx === itemsToReorder.length - 1;
  }

  const handleMove = useCallback(
    async (objectId: string, to: 'UP' | 'DOWN' | string) => {
      if (treeNode) {
        if (key === docTree.key) {
          await ctx2.commandCenters.assemblyCommands.reSort(objectId, to);
          userEvents.emit(PRODUCT_EVENT.ASSEMBLY_TREE_CHANGED);
        } else {
          const result =
            await ctx2.commandCenters.assemblyCommands.commandGateway(
              assembly.docid,
              assembly.docver,
              {
                c: 'ReSort',
                o: objectId.split(':').at(-1) || '',
                to: to.split(':').at(-1) || '',
              },
            );

          if (result.sub?.code !== 0) {
            MessageTip.error(
              `重新排序失败，请稍后再试 - ${result.sub.message}（Code ${result.sub.code}）`,
            );

            return;
          } else {
            const partKey = getPartRefKey(assembly);
            removeRefDocObjects(partKey);

            await buildAssemblyTree(docTree, {
              initialRender: false,
              noRender: true,
            });
          }
        }

        if (!['UP', 'DOWN'].includes(to)) {
          const titles = [objectId, to].map(
            (id) => itemsToReorder.find((item) => item.key === id)?.title,
          );

          setSelectedKeys([]);
          MessageTip.success(`${titles.join(' 与 ')} 已交换位置。`);
        }
      }
    },
    [key, assembly, docTree, itemsToReorder],
  );

  const handleMoveUp = () => handleMove(selectedKeys[0], 'UP');
  const handleMoveDown = () => handleMove(selectedKeys[0], 'DOWN');
  const handleSwap = () => handleMove(selectedKeys[0], selectedKeys[1]);

  useEffect(() => {
    if (!open) {
      setSelectedKeys([]);
    }
  }, [open]);

  return (
    <ConfigProvider theme={AntDesignTheme}>
      <DraggableModal
        open={open}
        title='重新排序'
        onCancel={onClose}
        footer={[
          <Button
            key='close'
            onClick={onClose}
            type='primary'
          >
            关闭
          </Button>,
        ]}
        classNames={{
          body: 'overflow-hidden',
        }}
        width={320}
        maskClosable={false}
      >
        <Row
          gutter={24}
          align='top'
        >
          <Col flex='auto'>
            <MultipleSelectList<IAssemblyDocTreeNode, string>
              items={itemsToReorder}
              maxItemsToSelect={2}
              selectedKeys={selectedKeys}
              onSelect={setSelectedKeys}
              getKey={(item) => item.key}
              renderItem={(item) => <span>{item.title}</span>}
            />
          </Col>
          <Col>
            <Space
              direction='vertical'
              size='middle'
            >
              <Tooltip
                title='向上'
                placement='right'
              >
                <Button
                  key='up'
                  size='small'
                  onClick={handleMoveUp}
                  disabled={!canMove || isFirst}
                  style={{ width: 64 }}
                >
                  <VscArrowUp />
                </Button>
              </Tooltip>
              <Tooltip
                title='向下'
                placement='right'
              >
                <Button
                  key='down'
                  size='small'
                  onClick={handleMoveDown}
                  disabled={!canMove || isLast}
                  style={{ width: 64 }}
                >
                  <VscArrowDown />
                </Button>
              </Tooltip>
              <Tooltip
                title='交换'
                placement='right'
              >
                <Button
                  key='swap'
                  size='small'
                  onClick={handleSwap}
                  disabled={!canSwap}
                  style={{ width: 64 }}
                >
                  <VscGitCompare />
                </Button>
              </Tooltip>
            </Space>
          </Col>
        </Row>
      </DraggableModal>
    </ConfigProvider>
  );
};

export default ResortDocModal;
